package service

import (
	"duoke/internal/dao"
	"duoke/internal/model/entity"
	"duoke/model"
	"duoke/tables"
	utils "duoke/utils/common"
	"duoke/utils/gconv"
	"duoke/utils/orm"
	"errors"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/gogf/gf/v2/container/garray"
	"github.com/gogf/gf/v2/text/gstr"
	"strings"
)

var CourseVideo = new(courseVideoService)

type courseVideoService struct {
	TablesName string
}

func (s *courseVideoService) Init() *courseVideoService {
	s.TablesName = "course_video"
	return s
}

// Save 保存
func (s *courseVideoService) Save(c *gin.Context, req *model.CourseVideoTab) (int64, error) {
	accountR, _ := Request.Account(c)
	req.Acid = accountR.Id
	var err error
	key := []byte("Q!fqhthlsFuazZ(gvlWTY(h(n_x*2i4+")
	iv := []byte("Js8K1kDYC^K^FuWZ")
	if req.GatherUrl != "" {
		req.Url, err = tableCommon.SaveVideo(c, req.GatherUrl)
		if err != nil {
			return 0, nil
		}
	}
	req.Url, err = utils.Common.AESEncrypt([]byte(req.Url), key, iv)
	if err != nil {
		return 0, err
	}
	where := ""
	if req.Id > 0 {
		where = fmt.Sprintf("id=%d", req.Id)
	}
	req.Acid = accountR.Id
	var data int64
	if req.Id > 0 {
		data, err = orm.Db.Where(where).AllCols().Update(req)
	} else {
		data, err = tableCommon.SaveData(s.TablesName, req, where, "insert")
	}
	if err != nil {
		return 0, err
	}
	return data, err
}

func (s *courseVideoService) List(c *gin.Context, req *model.ReqList) (*[]tables.CourseVideo, int64, error) {
	// 查询结果
	where := ""
	if req.Keyword != "" {
		where = fmt.Sprintf("title like '%s'", "%"+req.Keyword+"%")
	}
	var list []tables.CourseVideo
	total, err := tableCommon.QueryListWithPageV2(where, req.PageNo,
		req.PageSize).OrderBy("id desc").FindAndCount(&list)

	if err != nil {
		return nil, 0, err
	}
	key := []byte("Q!fqhthlsFuazZ(gvlWTY(h(n_x*2i4+")
	iv := []byte("Js8K1kDYC^K^FuWZ")
	for k, m := range list {
		list[k].Url, _ = utils.Common.AESDecrypt(m.Url, key, iv)
	}
	return &list, total, nil
}
func (s *courseVideoService) Del(id int) (int64, error) {
	i, err := orm.Db.ID(id).Delete(&tables.CourseVideo{})
	if err != nil {
		return 0, err
	}
	return i, nil
}

// Info 获取栏目
func (s *courseVideoService) Info(c *gin.Context, id int, Type int, fields string) (*[]model.CVRsp, error) {
	var m []model.CourseVideoRsp
	user, err := Request.User(c)
	var isBuy int
	err = orm.Db.Where("list_id=? and type=?", id, Type).Cols(fields).Find(&m)
	// 1 判断该目录有没有被购买 判断is_feel是否等于1 免费
	var ids []int
	if user.Id != 0 {
		info, err := User.Info(c, "phone")
		if err != nil {
			return nil, errors.New("用户获取失败")
		}
		// 如果主目录免费
		where := "id=?"
		var cl entity.CourseList
		err = dao.CourseList.Ctx(c).Where(where, id).Scan(&cl)
		if err != nil {
			return nil, errors.New("课程获取失败")
		}
		if cl.IsFeel == 1 || (cl.WhiteList != "" || gstr.InArray(gstr.Split(info.Phone, ","), cl.WhiteList)) {
			isBuy = 1
		} else {
			// 判断主目录有没有被购买 主目录如果被购买了 其他目录则是全部被购买状态
			where = "video_id = ? and user_id=? and state=1 and is_effective > 1"
			count, err := dao.CourseOrder.Ctx(c).Where(where, id, user.Id).Fields("id").Count()
			if err != nil {
				return nil, err
			}
			if count > 0 {
				isBuy = 1
			} else {
				// 3 判断购买的是否已过期
				for k, item := range m {
					// 判断参数是否在允许的范围内
					if info.Phone != "" && gstr.InArray(gstr.Split(info.Phone, ","), item.WhiteList) {
						m[k].IsFeel = 1
						continue
					}
					if item.IsFeel == 2 {
						ids = append(ids, item.Id)
					}
				}
				where = "video_id in (?) and user_id=? and state=1 and is_effective > 1"
				var order []tables.CourseOrder
				err = dao.CourseOrder.Ctx(c).Where(where, ids, user.Id).Fields("id,video_id").Scan(&order)
				if err != nil {
					return nil, err
				}
				// 初始化int数组 复用
				ids = []int{}
				for _, item := range order {
					ids = append(ids, item.VideoId)
				}
			}
		}
	}

	// 判断主目录是否已被购买
	var cvRsp []model.CVRsp
	for _, item := range m {
		if isBuy == 1 || item.IsFeel == 1 {
			item.IsBuy = 1
		} else {
			if garray.NewIntArrayFrom(ids).Contains(item.Id) {
				item.IsBuy = 1
			}
		}
		cvRsp = append(cvRsp, model.CVRsp{
			Id:               item.Id,
			Url:              item.Url,
			Title:            item.Title,
			Type:             item.Type,
			Duration:         item.Duration,
			Price:            item.Price,
			LearningProgress: item.CourseProgress.LearningProgress,
			IsBuy:            item.IsBuy,
			IsPoints:         item.IsPoints,
			WatchType:        item.WatchType,
			CarmineId:        item.CarmineId,
			IsFeel:           item.IsFeel,
		})
	}
	if err != nil {
		return nil, err
	}
	return &cvRsp, nil
}
func (s *courseVideoService) checkOrder(id int) {

}

// 赠送积分
func (s *courseVideoService) GivePoints(c *gin.Context, req *model.ReqGivePoints) error {
	user, err := Request.User(c)
	if err != nil {
		return err
	}
	var m tables.CourseProgress
	get, err := orm.Db.Where("from_id=? and user_id=? and acid=?", req.Id, user.Id, user.Acid).
		Cols("watch_type,list_id,id").Get(&m)
	if err != nil {
		return err
	}
	if !get {
		return errors.New("还未观看该视频")
	}
	if req.Type <= m.WatchType {
		return errors.New("已经赠送过了")
	}
	var m1 tables.CourseList
	get, err = orm.Db.Where("id=?", m.ListId).Cols("watch_points").Get(&m1)
	if !get {
		return errors.New("视频不存在1")
	}
	if err != nil {
		return err
	}
	// 赠送
	split := strings.Split(m1.WatchPoints, ",")
	count := len(split)
	if req.Type > count {
		return errors.New("赠送类型错误【type】")
	}
	points := split[req.Type-1]
	// 赠送积分
	err = User.Score(c, user.Id, gconv.Int(points), "观看课程赠送积分")
	if err != nil {
		return err
	}
	_, err = orm.Db.Where("id=?", m.Id).Update(&tables.CourseProgress{WatchType: req.Type})
	return err
}
func (s *courseVideoService) SaveWatch(c *gin.Context, req *model.ReqId) error {
	user, err := Request.User(c)
	if err != nil {
		return err
	}
	var m1 tables.Shortvideo
	get, err := orm.Db.Where("id=?", req.Id).Get(&m1)
	if err != nil || !get {
		return errors.New("视频不存在")
	}
	var m tables.ShortWatch
	get, err = orm.Db.Where("from_id=? and user_id=?", req.Id, user.Id).Get(&m)
	if err != nil {
		return err
	}
	var isNew int
	m.WatchNumber += 1
	m.FromId = req.Id
	m.UserId = user.Id
	m.SubMchId = m1.SubMchId
	m.Acid = user.Acid
	if get {
		_, err = orm.Db.Where("from_id=? and user_id=?", req.Id, user.Id).Update(&m)
		if err != nil {
			return err
		}
	} else {
		isNew = 1
		_, err = orm.Db.Insert(&m)
		if err != nil {
			return err
		}
	}
	m1.Watch += isNew
	_, err = orm.Db.Where("id=?", req.Id).Update(&m1)
	return err
}
